#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <termios.h>
int set_config(int serial_fd, int baud_rate, int data_bits, char parity, int stop_bits);

int open_serial(const char *serial_port)
{
	int serial_fd = 0;
	serial_fd = open(serial_port, O_RDWR | O_NOCTTY | O_NDELAY);
	if (serial_fd < 0)
	{
		printf("open serial port error\n");
		return;
    }

	if (fcntl(serial_fd, F_SETFL, 0) < 0)
	{
		printf("fcntl F_SETFL error\n");
    }
	if (isatty(serial_fd) == 0)
    {
      printf("This is not a terminal device\n");
    }
  	set_config(serial_fd,19200, 8, 'N', 1);/*缺省配置*/
	return serial_fd;
}

int set_config(int serial_fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
	int speed;
	struct termios new_cfg, old_cfg;
	if (tcgetattr(serial_fd, &old_cfg) != 0)
    {
      printf("tcgetattr error\n");
      return (-1);
    }
	new_cfg = old_cfg;
	cfmakeraw(&new_cfg);
	new_cfg.c_cflag &= ~CSIZE;

	switch (baud_rate)
	{
		case 2400:
		{
			speed = B2400;
		}break;
		case 4800:
		{
			speed = B4800;
		}break;
		case 9600:
		{
			speed = B9600;
		}break;
		case 19200:
		{
			speed = B19200;
		}break;
		case 38400:
		{
			speed = B38400;
		}
		break;
		default:
			case 115200:
			{
				speed = B115200;
			}break;
    }
	cfsetispeed(&new_cfg, speed);
	cfsetospeed(&new_cfg, speed);

	switch (data_bits)
	{
		case 7:
		{
			new_cfg.c_cflag |= CS7;
		}break;

		default:
		case 8:
		{
			new_cfg.c_cflag |= CS8;
		}break;
	}
	switch (parity)
	{
		default:
		case 'n':
		case 'N':
		{
			new_cfg.c_cflag &= ~PARENB;
			new_cfg.c_iflag &= ~INPCK;
		}break;

		case 'o':
		case 'O':
		{
			new_cfg.c_cflag |= (PARODD | PARENB);
			new_cfg.c_iflag |= INPCK;
		}break;
		case 'e':
		case 'E':
		{
			new_cfg.c_cflag |= PARENB;
			new_cfg.c_cflag &= ~PARODD;
			new_cfg.c_iflag |= INPCK;
    	}break;

		case 's':
		case 'S':
		{
			new_cfg.c_cflag &= ~PARENB;
			new_cfg.c_iflag &= ~CSTOPB;
		}break;
	}

	switch (stop_bits)
	{
		default:
		case 1:
		{
			new_cfg.c_cflag &= ~CSTOPB;
		}break;

		case 2:
		{
			new_cfg.c_cflag |= CSTOPB;
		}break;
    }

	new_cfg.c_cc[VTIME] = 0;
	new_cfg.c_cc[VMIN] = 1;
	tcflush(serial_fd, TCIFLUSH);
	if ((tcsetattr(serial_fd, TCSANOW, &new_cfg)) != 0)
    {
		printf("tcsetattr error\n");
		return (-1);
    }

  return 0;
}
